/*
 *  Librarie de tipuri de date abstracte (TDA)
 
    Copyright (C) 2007  Catedra de Structuri de Date

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License along
    with this program; if not, write to the Free Software Foundation, Inc.,
    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

/**
@file arraylist.h
@author Stefan Bucur
@brief This header file contains the structures and functions need to work with
array lists (lists implemented using C arrays)

It contains functions for creating an array list, destroying it, manipulating
elements, finding an element, as well as checking a list's size.
*/

#ifndef ARRAYLIST_H_
#define ARRAYLIST_H_

struct arraylist_adt;

/**
@brief Structure representing an array-list.

 The structure contains pointers to the data stored in the list. The number of
elements and current capacity of the list are also stored. Directly modifying
structure memebers is not recommended. To manipulate data in the list, use the
appropriate functions.

Element data is stored using a void pointer. Thus, one should note that there is
no way to tell what kind of data is stored in the list or in a particular element
of the list.

@see AL_New(), AL_Free()
 */
typedef struct arraylist_adt *ArrayList;

/**
@brief Array-list iterator definition.

 Although in this implementation the array list iterator is an \c int one should
not use \c int directly, as this might change without notice in future versions
of the file (e.g. using \c long for a x64 edition of the library).

@see AL_Find(), AL_Begin, AL_End(), AL_Next(), AL_Add(), AL_Remove()
*/
typedef int ArrayListIterator;

/**
@brief Creates a new array list with the specified initial capacity.

This function creates a new array list and reserves space for \a initcap elements.
If, during usage, the initial capacity is exceeded, then the arraylist 
automatically resizes in order to accomodate the elements.

@param initcap initial capacity of the list.
@return newly created array list.
*/
ArrayList AL_New(int initcap);

/**
@brief Destroys the specified array list.

This function destroys an array list and frees the memory used by it. Also, it
frees the memory used by the data stored in the list, so trying to access the
data in a destroyed list (e.g. through a pointer) will most likely result in a
Access violation / segfault.

@param list the list to be destroyed. A \c ArrayList structure.
*/
void AL_Free(ArrayList list);

/**
@brief Determines if the list is empty (has no elements) or not.

The function returns the value of <tt>count==0</tt>. The function returns 
regardless of the list capacity. 

@param list the list to be tested.
@return -1 if the list pointer is null (\a list ), 1 if the list is empty, 0
 otherwise.
*/
int AL_Empty(ArrayList list);

/**
@brief Returns the size of the array list.

The functions returns the number of elements in the array list. At any given 
time count \< capacity.

@param list list to be tested.
@return the number of elements in the list, or -1 if the \a list is \c NULL.
*/
int AL_Size(ArrayList list);

/**
@brief Gets the data stored at a given position.

The function returns the data stored at the position given by the iterator \a it
As \c void* is used to store data, a cast is needed to obtain the actual data.

@param list the list to retrieve data from.
@param it list iterator specifying the position to get data from.
@return the pointer to the data, or \c NULL if \a list is \c NULL or \a it does
not belong to the list.
*/
void *AL_Get(ArrayList list, ArrayListIterator it);

/**
@brief Updates the data contained in the specified position from the list.

The function updates the data of the element specified by the iterator \a it .
The old data is discared and the element will point to the new data.

@param list the list to update data in.
@param it iterator giving the position of the element whose data is to be
updated.
@param *el \c void* pointer to a memory location containing new data.
*/
void AL_Update(ArrayList list, ArrayListIterator it, void *el);

/**
@brief Searches for data in the list.

The function searches for the data specified by the \a el in the given list.

@note This version of ArrayList uses for comparision strict pointer comparison.
Further versions may include the possibilty to specify a comparator to provide
more flexible searching.

@param list the list in which to search.
@param *el data to search for.
@return returns an \c ArrayListIterator pointing to the position in the list
where the data was found, or \c NULL otherwise.
*/
ArrayListIterator AL_Find(ArrayList list, void *el);

/**
@brief Removes the specified element from the list.

The function removes the element specified by the iterator \a it from the list
\a list. The memory for the data stored in the element is not freed.

@param list the list from which to remove the element.
@param it iterator specifying the position of the element to be removed.
@return the data stored at the location specified by the iterator. If the
iterator does not exist in the list, points to the end of the list, or \a list
is \c NULL the function returns \c NULL.
*/
void *AL_Remove(ArrayList list, ArrayListIterator it);

/**
@brief Inserts data in the list, before the specified position.

The function adds the data specified by the \a el \c void* pointer in the list,
at the position specified by the \a it iterator. A new element is created and 
inserted before \a it .

The \a el pointer must point to a memory zone which has been already initialized
and holds the data to be stored in the list. The function doesn't make any kind
of verifications regarding the value of \a el .

@param list the list in which to add.
@param it iterator specifying the position to add.
@param *el element data.
*/
void AL_Add(ArrayList list, ArrayListIterator it, void *el);

/**
@brief Returns an iterator to the first element in the list.

The functions returns an iterator to the first element in the list.

@param list list to get the iterator to the first element of.
@return an \c ArrayListIterator to the first element in the list. It will have the value \c -1 if the list is \c NULL.
*/
ArrayListIterator AL_Begin(ArrayList list);

/**
@brief Returns an interator after the last element in the list.

The function returns an iterator at the end of the list. This iterator can be
used to insert data at the end of the list.

@param list an iterator for this list will be returned.
@return \c ArrayListIterator . The value (integer) is the same as the result of
\c AL_Size() for the specified list.
*/
ArrayListIterator AL_End(ArrayList list);

/**
@brief Returns an iterator to the next element in the list.

The function returns an iterator to the next element in the list. The current
element is given through an interator, obtained through a call to \c AL_Begin()
or subsequent calls to \c AL_Next().

@param list the list for which the next element is required.
@param it iterator specifying current position in the list.
@return an iterator to the next element in the list or the value \c -1 if
either the iterator points to \c LL_End() or the list is \c NULL.
*/
ArrayListIterator AL_Next(ArrayList list, ArrayListIterator it);

#endif /*ARRAYLIST_H_*/
